home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
drdobbs
/
1991
/
12
/
memanage.asc
< prev
next >
Wrap
Text File
|
1991-11-11
|
7KB
|
299 lines
_A SIMPLE HANDLE-BASED MEMORY MANAGER_
by David Betz
[LISTING ONE]
/* hmm.h - definitions for a simple handle based memory manager */
typedef char **HANDLE;
/* heap header structure */
typedef struct heaphdr {
int hh_nhandles; /* number of handles */
char *hh_next; /* next free location */
char *hh_base; /* base of heap memory */
char *hh_top; /* top of heap memory */
HANDLE hh_handles; /* base of handle array */
} HEAPHDR;
HEAPHDR *NewHeap(int,int);
void FreeHeap(HEAPHDR *);
HANDLE HeapAlloc(HEAPHDR *,int);
void HeapFree(HEAPHDR *,HANDLE);
[LISTING TWO]
/* hmm.c - a simple handle based memory manager -- by David Betz */
#include <stdio.h>
#include "hmm.h"
/* number of handles to add when expanding the handle table */
#define HINC 32
/* block prefix structure */
typedef struct blockpfx {
HANDLE bp_handle; /* handle for this block */
} BLOCKPFX;
/* block suffix structure */
typedef struct blocksfx {
int bs_size; /* size of block */
} BLOCKSFX;
static HANDLE FindMemory(HEAPHDR *,HANDLE,int);
static HANDLE NewHandle(HEAPHDR *);
static HANDLE UnusedHandle(HEAPHDR *);
static void ExpandHandleTable(HEAPHDR *,int);
static void CompactHeap(HEAPHDR *);
/* NewHeap - allocate and initialize a new heap */
HEAPHDR *NewHeap(nhandles,nbytes)
int nhandles; /* initial number of handles */
int nbytes; /* initial number of free bytes */
{
char *malloc();
HEAPHDR *h;
int tsize;
HANDLE p;
tsize = nhandles * sizeof(char *);
if ((h = (HEAPHDR *)malloc(sizeof(HEAPHDR) + tsize + nbytes)) == NULL)
return (NULL);
h->hh_nhandles = nhandles;
h->hh_handles = p = (HANDLE)((char *)h + sizeof(HEAPHDR));
while (--nhandles >= 0) *p++ = NULL;
h->hh_base = (char *)h->hh_handles + tsize;
h->hh_top = h->hh_base + nbytes;
h->hh_next = h->hh_top;
return (h);
}
/* FreeHeap - free a heap allocated by NewHeap() */
void FreeHeap(h)
HEAPHDR *h; /* heap to free */
{
free(h);
}
/* HeapAlloc - allocate a block of memory from the heap */
HANDLE HeapAlloc(h,size)
HEAPHDR *h; /* the heap */
int size; /* size of block to allocate */
{
HANDLE p;
if ((p = NewHandle(h)) == NULL)
return (NULL);
return (FindMemory(h,p,size));
}
/* HeapFree - free a block of memory allocated by HeapAlloc() */
void HeapFree(h,p)
HEAPHDR *h; /* the heap */
HANDLE p; /* the handle to free */
{
BLOCKPFX *bp;
bp = (BLOCKPFX *)(*p - sizeof(BLOCKPFX));
bp->bp_handle = NULL;
*p = NULL;
}
static HANDLE NewHandle(h)
HEAPHDR *h; /* the heap */
{
HANDLE p;
if ((p = UnusedHandle(h)) == NULL)
ExpandHandleTable(h,HINC);
return (UnusedHandle(h));
}
static HANDLE UnusedHandle(h)
HEAPHDR *h; /* the heap */
{
HANDLE p;
int n;
for (p = h->hh_handles, n = h->hh_nhandles; --n >= 0; ++p)
if (*p == NULL)
return (p);
return (NULL);
}
static void ExpandHandleTable(h,n)
HEAPHDR *h; /* the heap */
int n; /* number of handles to add */
{
char *base;
HANDLE p;
CompactHeap(h);
base = h->hh_base + (n * sizeof(char *));
if (base <= h->hh_next) {
p = (HANDLE)h->hh_base;
h->hh_base = base;
h->hh_nhandles += n;
while (--n >= 0)
*p++ = NULL;
}
}
static HANDLE FindMemory(h,p,size)
HEAPHDR *h; /* the heap */
HANDLE p; /* the handle to allocate space for */
int size; /* size of block to allocate */
{
BLOCKPFX *bp;
BLOCKSFX *bs;
int tsize;
char *d;
tsize = sizeof(BLOCKPFX) + size + sizeof(BLOCKSFX);
if ((d = h->hh_next - tsize) < h->hh_base) {
CompactHeap(h);
if ((d = h->hh_next - tsize) < h->hh_base)
return (NULL);
}
h->hh_next = d;
bp = (BLOCKPFX *)d;
bp->bp_handle = p;
d += sizeof(BLOCKPFX);
bs = (BLOCKSFX *)(d + size);
bs->bs_size = size;
*p = d;
return (p);
}
static void CompactHeap(h)
HEAPHDR *h; /* the heap */
{
char *src,*dst;
BLOCKPFX *hp;
BLOCKSFX *hs;
src = dst = h->hh_top;
while (src > h->hh_next) {
hs = (BLOCKSFX *)(src - sizeof(BLOCKSFX));
hp = (BLOCKPFX *)((char *)hs - hs->bs_size - sizeof(BLOCKPFX));
if (hp->bp_handle) {
if (src == dst)
src = dst = (char *)hp;
else {
while (src > (char *)hp)
*--dst = *--src;
*hp->bp_handle = dst + sizeof(BLOCKPFX);
}
}
else
src = (char *)hp;
}
h->hh_next = dst;
}
[LISTING THREE]
OFILES=hmmtest.obj hmm.obj
hmmtest.exe: $(OFILES)
cl $(OFILES)
[LISTING FOUR]
#include <stdio.h>
#include "hmm.h"
HANDLE allocshow(int);
void showheap(void);
void pause(void);
#define HMAX 100
HEAPHDR *h;
HANDLE handles[HMAX];
main()
{
int i;
/* allocate a heap */
h = NewHeap(16,4096);
showheap();
pause();
/* allocate a bunch of blocks of memory from the heap */
printf("Allocating...\n");
for (i = 0; i < HMAX; ++i) {
printf("%2d: ",i);
handles[i] = allocshow(32);
sprintf(*handles[i],"%d",i); /* put something in the block */
putchar('\n');
}
/* show the state of the heap after the allocations */
showheap();
pause();
/* free every other block (to test the compaction algorithm) */
printf("Deallocating...\n");
for (i = 0; i < HMAX; i += 2)
HeapFree(h,handles[i]);
/* show the state of the heap after the deallocations */
showheap();
pause();
/* now reallocate the blocks we freed (causes compaction) */
printf("Reallocating...\n");
for (i = 0; i < HMAX; i += 2) {
printf("%2d: ",i);
handles[i] = allocshow(32);
sprintf(*handles[i],"%d",i);
putchar('\n');
}
/* show the state of the heap after the new allocations */
showheap();
pause();
/* make sure all of the blocks contain what we expect */
printf("Checking...\n");
for (i = 0; i < HMAX; ++i) {
printf("%2d: %04x->%04x=",i,handles[i],*handles[i]);
printf("%s",*handles[i]);
if (atoi(*handles[i]) != i)
printf(" *** ERROR");
putchar('\n');
}
/* free the heap and exit */
FreeHeap(h);
}
HANDLE allocshow(size)
int size;
{
HANDLE p;
if (p = HeapAlloc(h,size))
printf("%04x->%04x",p,*p);
return (p);
}
void pause()
{
while (getchar() != '\n')
;
}
void showheap()
{
printf("nhandles: %d\n",h->hh_nhandles);
printf("handles: %04x\n",h->hh_handles);
printf("base: %04x\n",h->hh_base);
printf("next: %04x\n",h->hh_next);
printf("top: %04x\n",h->hh_top);
}